﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

// qt headers
#include <QIcon>
#include <QBrush>
#include <QImage>
#include <QFileInfo>
#include <QMap>

#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlResult>

// custom headers
#include "ProjectComponentsTableModel.h"
#include "ProjectComponentsTableSymbols.h"
#include "ProjectCloudComponentService.h"
#include "IGmepGcsProjectManager.h"
#include "UrlImageProvider.h"
#include "PathUtils.h"
#include "AppService.h"
#include "ProjectLoadedComponentService.h"
#include "GmepLocalDbService.h"
#include "GncINetworkCheck.h"
#include "GmepFilePathSettings.h"
#include "GbmpFileSystem.h"
#include "ComponentHttpUtils.h"
#include "BnufBulletin.h"
#include "ProjectChangedCache.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 
namespace gmepgcs 
{
    ProjectComponentsTableModel::ProjectComponentsTableModel(QObject *parent) : QAbstractTableModel(parent),
        m_vComponents(),
        m_spUrlThumbnailProvider(std::make_shared<UrlImageProvider>()),
        m_mpCheckSates(),
        m_isEditOperationVisible(true)
    {
        connect(m_spUrlThumbnailProvider.get(), &UrlImageProvider::OnProvided, this, &ProjectComponentsTableModel::UpdateThumbnail);
    }

    ProjectComponentsTableModel::~ProjectComponentsTableModel()
    {
    }

    int ProjectComponentsTableModel::rowCount(const QModelIndex & parent) const
    {
        if (parent.isValid())
        {
            return 0;
        }
        
        return (int)m_vComponents.size();
    }

    int ProjectComponentsTableModel::columnCount(const QModelIndex & parent) const
    {
        Q_UNUSED(parent);
        return COL_TOTAL_COUNT;
    }

    void ProjectComponentsTableModel::SetComponents(std::vector<std::shared_ptr<IProjectComponent>> components)
    {
        int32_t oldRowCount = rowCount();
        if (oldRowCount > 0)
        {
            beginRemoveRows(QModelIndex(), 0, oldRowCount - 1);
            removeRows(0, oldRowCount);
            endRemoveRows();
        }

        m_vComponents = components;
        m_mpCheckSates.clear();
        for (auto &item : m_vComponents)
        {
            if (item)
                m_mpCheckSates[item->Id] = false;
        }
        emit CheckStatesChanged(Qt::CheckState::Unchecked, 0);

        int32_t newRowCount = (int32_t)m_vComponents.size();
        if (newRowCount > 0)
        {
            beginInsertRows(QModelIndex(), 0, newRowCount - 1);
            insertRows(0, newRowCount);
            endInsertRows();
        }
        
        emit dataChanged(createIndex(0, 0), createIndex(newRowCount - 1, columnCount() - 1));
        emit TableUpdated();

        GetComponentIdTbl();

        // 若是公有云环境，则需要检查网络
        if (m_isPrivateEnv || ( gnc::INetworkCheck::Get() && gnc::INetworkCheck::Get()->CheckNetworkConnection()))
        {
            GetUpdateComponentIdList();
        }
    }

    void ProjectComponentsTableModel::UpdateThumbnail(std::wstring imageKey, std::shared_ptr<QImage> spImage)
    {
        int32_t rowCount = this->rowCount();
        for (int32_t i = 0; i != rowCount; ++i)
        {
            QModelIndex index = this->index(i, COL_COMPONENT_NAME, QModelIndex());
            if (index.isValid())
            {
                IProjectComponent *pComponent = static_cast<IProjectComponent *>(index.internalPointer());
                if (pComponent)
                {
                    std::wstring url = pComponent->Thumbnail;
                    if (url == imageKey)
                    {
                        if (spImage)
                        {
                            emit dataChanged(index, index, { Qt::DecorationRole });
                        }

                        return;
                    }
                }
            }
        }
    }

    void ProjectComponentsTableModel::ChangeCheckStates(Qt::CheckState state)
    {
        if (state == Qt::CheckState::PartiallyChecked)
        {
            return;
        }

        QModelIndex index;
        for (int32_t i = 0; i != rowCount(); ++i)
        {
            index = this->index(i, COL_CHECKBOX);
            bool oldValue = data(index, Qt::UserRole).toBool();
            bool newValue = state == Qt::CheckState::Checked;
            if (oldValue != newValue)
            {
                setData(index, newValue, Qt::UserRole);
            }
        }
    }

    void ProjectComponentsTableModel::ChangeCheckState(IProjectComponent *component, bool checked)
    {
        if (!component)
        {
            return;
        }

        for (int i = 0; i < rowCount(); ++i)
        {
            auto index = this->index(i, COL_CHECKBOX);
            if (!index.isValid())
            {
                continue;
            }

            auto pComponent = static_cast<IProjectComponent*>(index.internalPointer());
            if (!pComponent)
            {
                continue;
            }

            if (pComponent->Id == component->Id)
            {
                auto oldValue = data(index, Qt::ItemDataRole::UserRole);
                if (oldValue != checked)
                {
                    setData(index, checked, { Qt::ItemDataRole::UserRole });
                }
                return;
            }
        }
    }

    void ProjectComponentsTableModel::SetIsEditOperationVisible(bool isEditOperationVisible)
    {
        m_isEditOperationVisible = isEditOperationVisible;
    }

    void ProjectComponentsTableModel::OnItemCheckStateChanged()
    {
        int32_t checkedCount = 0;
        for (auto &item : m_mpCheckSates)
        {
            if (item)
            {
                ++checkedCount;
            }
        }

        Qt::CheckState state = Qt::CheckState::Unchecked;
        if (checkedCount >= m_mpCheckSates.count())
        {
            state = Qt::CheckState::Checked;
        }
        else if (checkedCount > 0)
        {
            state = Qt::CheckState::PartiallyChecked;
        }

        emit CheckStatesChanged(state, checkedCount);
    }
        
    QVariant ProjectComponentsTableModel::data(const QModelIndex & index, int role) const
    {
        if (!index.isValid())
        {
            return QVariant();
        }

        int row = index.row();
        int col = index.column();

        if (row >= m_vComponents.size()) 
        {
            return QVariant();
        }
        
        IProjectComponent *component = static_cast<IProjectComponent*>(index.internalPointer());
        if (!component)
        {
            return QVariant();
        }
        
        // 复选框
        if (col == COL_CHECKBOX)
        {
            switch (role)
            {
            case Qt::UserRole:
                return m_mpCheckSates[component->Id];
            default:
                break;
            }
        }
        gcmp::IDocument* pDoc = AppService::GetCurrentDocument();
        // 构件名
        if (col == COL_COMPONENT_NAME) 
        {
            switch (role) {
            case Qt::CheckStateRole:
                return QVariant();
            case Qt::DecorationRole:
            {
                if (component->IsProcessing())
                {
                    return QIcon(":/images/pic_component_thumbnail_processing.png");
                }

                if (component->IsProcessedFailed())
                {
                    return QIcon(":/images/pic_component_thumbnail_process_failed.png");
                }

                //std::wstring url = component->Thumbnail;
                QString filePath = QString::fromStdWString(component->Thumbnail); //QString::fromStdWString(PathUtils::GetThumbnailDownloadFilePath(url, L".png"));
                QFileInfo fileInfo(filePath);
                if (fileInfo.exists())
                {
                    return QIcon(filePath);
                }
            }
            case Qt::DisplayRole:
            {
                if (!component->GetIsSyncable() && !component->GetIsUpdatable())
                {
                    // 云端此构件的版本号与本地缓存的版本号比较
                    auto itr = m_mapUpdateComponentIdList.find(component->Id);
                    if (itr != m_mapUpdateComponentIdList.end())
                    {
                        int iCloudVersion = itr->second;
                        if(iCloudVersion > component->Version)
                            component->SetIsSyncable(true);
                    }
                }
                return QString::fromStdWString(component->GetDisplayName());
            }
            case Qt::TextAlignmentRole:
                return (int)Qt::AlignLeft | Qt::AlignVCenter;
            case Qt::ToolTipRole:
            {
                if (ProjectLoadedComponentService::Get()->IsComponentUpdatable(component->Id, component->Version))
                {
                    return QString::fromStdWString(GBMP_TR(L"有新版本可更新至当前工作单元"));
                }
                break;
            }
            default:
                break;
            }
        }
        // 状态
        else if (col == COL_COMPONENT_STATUS) 
        {
            switch (role) {
            case Qt::DisplayRole:
                return QString::fromStdWString(GBMP_TR(L"未载入"));
            case Qt::TextAlignmentRole:
                return (int)Qt::AlignCenter;
            default:
                break;
            }
        }
        // 操作 - 同步
        else if (col == COL_COMPONENT_OPERARION_SYNC)
        {
            switch (role) {
            case Qt::DisplayRole:
            {
                if (!m_isEditOperationVisible || component->Status.empty())
                {
                    return QString();
                }


                    if (!m_isPrivateEnv && (!gnc::INetworkCheck::Get() || !gnc::INetworkCheck::Get()->CheckNetworkConnection()))
                    {
                        return QString();
                    }
                    
                    int iDirtyFlag = 0;
                    int iVersion = 1; //本地
                    if (m_mapComponentId.contains(component->Id))
                    {
                        std::tie(iVersion, iDirtyFlag) = m_mapComponentId[component->Id];
                    }
                    bool bSyn1 = true;
                    if (0 == iDirtyFlag)
                    {
                        bSyn1 = false;
                    }
                    if (bSyn1)
                        return QString::fromStdWString(GBMP_TR(L"同步"));

                    bool bSyn2 = false;
                    // 云端此构件的版本号与本地缓存的版本号比较
                    auto itr = m_mapUpdateComponentIdList.find(component->Id);
                    if (itr != m_mapUpdateComponentIdList.end())
                    {
                        int iCloudVersion = itr->second;                        
                        bSyn2 = iCloudVersion > iVersion;          
                    }
                    if (bSyn2)
                        return QString::fromStdWString(GBMP_TR(L"同步"));

                    // 云端此构件的版本号与此工作单元已载入族的版本号比较
                    bool bSync3 = ProjectLoadedComponentService::Get()->IsComponentUpdatable(component->Id, component->Version);
                    if (bSync3)
                        return QString::fromStdWString(GBMP_TR(L"同步"));
                    
                    return QString();


                if (component->IsReleased())
                {
                    if (ProjectLoadedComponentService::Get()->IsComponentLoadedByCloudId(pDoc, component->Id))
                    {
                        if (ProjectLoadedComponentService::Get()->IsComponentUpdatable(component->Id, component->Version))
                        {
                            return QString::fromStdWString(GBMP_TR(L"更新"));
                        }
                        else
                        {
                            return QString();
                        }
                    }
                    else
                    {
                        return QString();
                    }
                }

                if (component->IsProcessing())
                {
                    return QString::fromStdWString(GBMP_TR(L"删除"));
                }

                if (component->IsProcessedFailed())
                {
                    return QString::fromStdWString(GBMP_TR(L"删除"));
                }
                
                if (component->IsDeleted())
                {
                    return QString::fromStdWString(GBMP_TR(L"删除"));
                }
            
                return QString();
            }               
            case Qt::TextAlignmentRole:
                return (int)Qt::AlignLeft | Qt::AlignVCenter;
            case Qt::TextColorRole:
                return QColor(0, 177, 209);
            default:
                break;
            }
        }
        // 操作 - 布置
        else if (col == COL_COMPONENT_OPERARION_PLACE)
        {
            switch (role) {
            case Qt::DisplayRole:
            {
                if (component->Status.empty())
                {
                    return QString();
                }

                if (AppService::IsGmep())
                {
                    return QString::fromStdWString(GBMP_TR(L"布置"));
                }

                return QString();
            }

            case Qt::TextAlignmentRole:
                return (int)Qt::AlignLeft | Qt::AlignVCenter;
            case Qt::TextColorRole:
                return QColor(0, 177, 209);
            default:
                break;
            }
        }
        // 操作 - 载入
        else if (col == COL_COMPONENT_OPERARION_LOADINTO) 
        {
            switch (role) {
            case Qt::DisplayRole:
            {
                if (!m_isEditOperationVisible || component->Status.empty())
                {
                    return QString();
                }

                if (component->IsReleased())
                {
                    if (ProjectLoadedComponentService::Get()->IsComponentLoadedByCloudId(pDoc, component->Id))
                    {
                        if (ProjectLoadedComponentService::Get()->IsComponentUpdatable(component->Id, component->Version))
                        {
                            // return QString::fromStdWString(L"更新");
                        }
                    }
                    else
                    {
                        return QString::fromStdWString(GBMP_TR(L"载入"));
                    }
                }

                if (component->IsProcessing())
                {
                    return QString();
                }

                if (component->IsProcessedFailed())
                {
                    return QString();
                }

                if (component->IsDeleted())
                {
                    return QString();
                }

                return QString();
            }
                
            case Qt::TextAlignmentRole:
                return (int)Qt::AlignLeft | Qt::AlignVCenter;
            case Qt::TextColorRole:
                return QColor(0, 177, 209);
            default:
                break;
            }
        }
        if (col == COL_COMPONENT_OPERARION_DELETE)
        {
            switch (role) {
            case Qt::DisplayRole:
            {
                if (!m_isEditOperationVisible || component->Status.empty())
                {
                    return QString();
                }

                if (component->IsReleased())
                {
                    return QString::fromStdWString(GBMP_TR(L"删除"));
                }

                if (component->IsProcessing())
                {
                    return QString();
                }

                if (component->IsProcessedFailed())
                {
                    return QString();
                }

                if (component->IsDeleted())
                {
                    return QString();
                }

                return QString();
            }

            case Qt::TextAlignmentRole:
                return (int)Qt::AlignLeft | Qt::AlignVCenter;
            case Qt::TextColorRole:
                return QColor(0, 177, 209);
            default:
                break;
            }
        }

        return QVariant();
    }

    QVariant ProjectComponentsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        switch (orientation) 
        {
        // 水平 headers
        case Qt::Horizontal:
            switch (section) 
            {
            // 复选框
            case COL_CHECKBOX:
            {
                switch (role)
                {
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"复选框"));
                default:
                    break;
                }

                break;
            }
            // 构件名
            case COL_COMPONENT_NAME:
            {
                switch (role)
                {
                case Qt::CheckStateRole:
                    return false;
                case Qt::DisplayRole:
                    return QString::fromStdWString(GBMP_TR(L"构件名"));
                case Qt::TextAlignmentRole:
                    return (int)Qt::AlignLeft | Qt::AlignVCenter;
                case Qt::BackgroundColorRole:
                {
                    QBrush red(Qt::red);
                    return red;
                }
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"构件名"));
                default:
                    break;
                }

                break;
            }
            // 状态
            case COL_COMPONENT_STATUS:
            {
                switch (role)
                {
                case Qt::DisplayRole:
                    return QString::fromStdWString(GBMP_TR(L"状态"));
                case Qt::TextAlignmentRole:
                    return Qt::AlignCenter;
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"构件状态"));
                default:
                    break;
                }

                break;
            }
            // 操作 - 同步
            case COL_COMPONENT_OPERARION_SYNC:
            {
                switch (role)
                {
                case Qt::DisplayRole:
                    return QVariant();
                case Qt::TextAlignmentRole:
                    return (int)Qt::AlignLeft | Qt::AlignVCenter;
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"操作1"));
                default:
                    break;
                }

                break;
            }
            // 操作 - 布置
            case COL_COMPONENT_OPERARION_PLACE:
            {
                switch (role)
                {
                case Qt::DisplayRole:
                    return QString::fromStdWString(GBMP_TR(L"操作"));
                case Qt::TextAlignmentRole:
                    return (int)Qt::AlignLeft | Qt::AlignVCenter;
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"操作2"));
                default:
                    break;
                }

                break;
            }
            // 操作 - 载入
            case COL_COMPONENT_OPERARION_LOADINTO:
            {
                switch (role)
                {
                case Qt::DisplayRole:
                    return QVariant();
                case Qt::TextAlignmentRole:
                    return (int)Qt::AlignLeft | Qt::AlignVCenter;
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"操作3"));
                default:
                    break;
                }

                break;
            }
            // 操作 - 删除
            case COL_COMPONENT_OPERARION_DELETE:
            {
                switch (role)
                {
                case Qt::DisplayRole:
                    return QVariant();
                case Qt::TextAlignmentRole:
                    return (int)Qt::AlignLeft | Qt::AlignVCenter;
                case Qt::AccessibleDescriptionRole:
                    return QString::fromStdWString(GBMP_TR(L"操作4"));
                default:
                    break;
                }

                break;
            }
            default:
                break;
            }
            break;
        // 垂直 headers
        case Qt::Vertical:
        {
            if (role == Qt::AccessibleDescriptionRole)
            {
                IProjectComponent *component = static_cast<IProjectComponent*>(index(section, COL_COMPONENT_NAME).internalPointer());
                if (component)
                {
                    return QString::fromStdWString(L"Comopnent{id:%1}")
                        .arg(QString::fromStdWString(component->Id));
                }

                return QString::fromStdWString(L"ROW_%1").arg(section);
            }

            break;
        }
        default:
            break;
        }

        return QVariant();
    }

    QModelIndex ProjectComponentsTableModel::index(int row, int column, const QModelIndex & parent) const
    {
        if (hasIndex(row, column, parent) && row >=0 && row < m_vComponents.size() && column < COL_TOTAL_COUNT)
        {
            //IProjectComponent *component = const_cast<IProjectComponent*>(m_vComponents[row].get());
            return createIndex(row, column, m_vComponents[row].get());
        }

        return QAbstractTableModel::index(row, column, parent);
    }

    void ProjectComponentsTableModel::RefreshComponent(const std::shared_ptr<IDetailedProjectComponent> detailedProjectComponent)
    {
        if (!detailedProjectComponent)
        {
            return;
        }

        for (int i = 0; i != rowCount(); ++i)
        {
            auto index = this->index(i, 0);
            if (index.isValid())
            {
                IProjectComponent *component = static_cast<IProjectComponent *>(index.internalPointer());
                if (component && component->Id == detailedProjectComponent->Id)
                {
                    component->Name = detailedProjectComponent->Name;
                    auto thumbnail = std::wstring();
                    std::wstring thumbnailSize = L"256";
                    std::wstring thumbnailAngle = L"0";
                    auto thumbnailSizeGroupIterator = detailedProjectComponent->Thumbnails.find(thumbnailSize);
                    if (thumbnailSizeGroupIterator != detailedProjectComponent->Thumbnails.end())
                    {
                        auto thumbnailName = QString::fromStdWString(thumbnailSize + L"_" + thumbnailAngle);
                        auto thumbnailSizeGroup = thumbnailSizeGroupIterator->second;
                        auto thumbnailIterator = std::find_if(thumbnailSizeGroup.begin(), thumbnailSizeGroup.end(), 
                            [thumbnailName](const std::vector<std::wstring>::value_type &thumb) {
                            QFileInfo fileInfo(QString::fromStdWString(thumb));
                            return fileInfo.completeBaseName() == thumbnailName;
                        });

                        if (thumbnailIterator != thumbnailSizeGroup.end())
                        {
                            thumbnail = *thumbnailIterator;
                        }
                        else if (thumbnailSizeGroup.begin() != thumbnailSizeGroup.end())
                        {
                            thumbnail = *thumbnailSizeGroup.begin();
                        }
                    }
                    component->Thumbnail = thumbnail;
                    component->Version = detailedProjectComponent->Version;
                    component->SetIsSyncable(detailedProjectComponent->GetIsSyncable());
                    component->SetIsUpdatable(detailedProjectComponent->GetIsUpdatable());
                    component->SetVersionInLocalDb(detailedProjectComponent->GetVersionInLocalDb());
                    component->SetVersionInDocument(detailedProjectComponent->GetVersionInDocument());

                    dataChanged(this->index(i, COL_COMPONENT_NAME), this->index(i, COL_COMPONENT_OPERARION_LOADINTO), {Qt::DisplayRole | Qt::DecorationRole});

                    break;
                }
            }
        }
    }

    void ProjectComponentsTableModel::RefreshComponent()
    {
        GetComponentIdTbl();
        GetUpdateComponentIdList();
    }

    bool ProjectComponentsTableModel::ExistsComponent(const std::wstring & componentId)
    {
        for (auto &item : m_vComponents)
        {
            if (item == nullptr)
            {
                continue;
            }
            if (item->Id == componentId)
            {
                return true;
            }
        }

        return false;
    }

    bool ProjectComponentsTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
    {
        if (!index.isValid())
        {
            return false;
        }

        IProjectComponent *component = static_cast<IProjectComponent *>(index.internalPointer());
        if (!component)
        {
            return false;
        }

        int32_t col = index.column();
        if (col == COL_CHECKBOX)
        {
            switch (role)
            {
            case Qt::UserRole:


                if (m_mpCheckSates.contains(component->Id))
                {                    
                    bool boolValue = value.toBool();
                    m_mpCheckSates[component->Id] = boolValue;
                    emit dataChanged(index, index, { role });
                    OnItemCheckStateChanged();
                    emit ComponentCheckStateChanged(component, boolValue);
                    return true;
                }
                break;
            default:
                break;
            }
        }

        return false;
    }

    void ProjectComponentsTableModel::GetComponentIdTbl()
    {
        m_mapComponentId.clear(); //Id, Version, DirtyFlag
        std::wstring sProductLibraryFileName = GmepFilePathSettings::GetCurrentProductDBFilePath();
        if (!gcmp::FileInfo(sProductLibraryFileName).Exists())
            return;

        QSqlDatabase database;
        if (QSqlDatabase::contains("qt_sql_default_connection"))
        {
            database = QSqlDatabase::database("qt_sql_default_connection");
        }
        else
        {
            database = QSqlDatabase::addDatabase("QSQLITE");
        }
        database.setDatabaseName(QString::fromStdWString(sProductLibraryFileName));

        if (!database.open())
        {
            return;
        }

        QSqlQuery query;
        std::wstring sQuery = L"select Id, Version, DirtyFlag from ComponentId";
        if (query.exec(QString::fromStdWString(sQuery)))
        {
            while (query.next())
            {
                m_mapComponentId[query.value(0).toString().toStdWString()] = std::make_tuple(query.value(1).toInt(), query.value(2).toInt());
            }
        }

        database.close();
    }

    void ProjectComponentsTableModel::GetUpdateComponentIdList()
    {
        m_mapUpdateComponentIdList.clear();

        std::map<std::wstring, int> addedComponentIdList;
        std::map<std::wstring, int> deletedComponentIdList;
        std::wstring currentProjectId = IProjectManager::Get()->GetCurrentProjectId();
        ProjectChangedCache::GetInstance()->GetProjectChangedIdListDuringTheTime(currentProjectId, addedComponentIdList, m_mapUpdateComponentIdList, deletedComponentIdList);
        ProjectChangedCache::GetInstance()->Clear();
    }

    void ProjectComponentsTableModel::SetIsPrivateEnv(bool isPrivateEnv)
    {
        m_isPrivateEnv = isPrivateEnv;
    }
}
